package Tester;

import GetOffEr.*;
import Lander.*;
import Flyer.*;
import Navigator.*;
import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.*;

import spaceCraft.*;

/**
 * Created by IntelliJ IDEA.
 * User: anton
 * Date: 30.03.12
 * Time: 12:55
 * To change this template use File | Settings | File Templates.
 */
public class SpaceCraftTest {

    private int ACCELERATION = 900;
    private String GET_OFF_MANUAL_GOOD_REPORT = "This garbage-can is still easy to handle!";
    private String GET_OFF_MANUAL_BAD_REPORT = "This stuff doesn't work again!";
    private String GET_OFF_AUTO_GOOD_REPORT = "Auto-get off..This garbage-can is doing everything for you!";
    private String GET_OFF_AUTO_BAD_REPORT = "Engine is broken..Next time I should check it first..";
    private String LAND_MANUAL_GOOD_REPORT = "Sometime it's better to do it by myself.";
    private String LAND_MANUAL_BAD_REPORT = "Maybe this stuff was made in China!";
    private String LAND_AUTO_GOOD_REPORT = "It's time to have a rest.";
    private String LAND_AUTO_BAD_REPORT = "It's a miracle this garbage-can wasn't blown at once!";

    private Engine shipEngine;
    private String TURBO_REPORT;
    private String AUTO_REPORT;
    private SpaceShip ship;

    @Before
    public void setUp() {
        shipEngine = new Engine(new ProductInfo("Foo", "kaka"), ACCELERATION);
        ship = new SpaceShip(new ProductInfo("JEtPack", "FireFly"), shipEngine);
        TURBO_REPORT = ("Velocity is over " + (shipEngine.getAcceleration() * 4) + " thousands km/sec.");
        AUTO_REPORT = ("Velocity is over " + shipEngine.getAcceleration() + " thousands km/sec.");
    }

    @Test
    public void shouldGetOffManualWithFixedEngine() {
        ship.setGetOffMode(new GetOffManually());
        ship.fixEngine();
        assertEquals(ship.getOff(), GET_OFF_MANUAL_GOOD_REPORT);
    }

    @Test
    public void shouldNotGetOffManualWithBrokenEngine() {
        ship.setGetOffMode(new GetOffManually());
        ship.breakEngine();
        assertEquals(ship.getOff(), GET_OFF_MANUAL_BAD_REPORT);
    }

    @Test
    public void shouldGetOffAutoWithFixedEngine() {
        ship.setGetOffMode(new GetOffUnderAutoPilot());
        ship.fixEngine();
        assertEquals(ship.getOff(), GET_OFF_AUTO_GOOD_REPORT);
    }

    @Test
    public void shouldNotGetOffAutoWithBrokenEngine() {
        ship.setGetOffMode(new GetOffUnderAutoPilot());
        ship.breakEngine();
        assertEquals(ship.getOff(), GET_OFF_AUTO_BAD_REPORT);
    }

    @Test
    public void shouldLandManualWithFixedEngine() {
        ship.setLandMode(new LandManually());
        ship.fixEngine();
        assertEquals(ship.land(), LAND_MANUAL_GOOD_REPORT);
    }

    @Test
    public void shouldNotLandManualWithBrokenEngine() {
        ship.setLandMode(new LandManually());
        ship.breakEngine();
        assertEquals(ship.land(), LAND_MANUAL_BAD_REPORT);
    }

    @Test
    public void shouldLandAutoWithFixedEngine() {
        ship.setLandMode(new LandUnderAutoPilot());
        ship.fixEngine();
        assertEquals(ship.land(), LAND_AUTO_GOOD_REPORT);
    }

    @Test
    public void shouldNotLandAutoWithBrokenEngine() {
        ship.setLandMode(new LandUnderAutoPilot());
        ship.breakEngine();
        assertEquals(ship.land(), LAND_AUTO_BAD_REPORT);
    }

    @Test
    public void shouldFlyUnderAuto() {
        ship.setFlyMode(new FlyUnderAutoPilot());
        assertEquals(ship.fly(), AUTO_REPORT);
    }

    @Test
    public void shouldFlyWithTurbo() {
        ship.setFlyMode(new FlyWithTurbo());
        assertEquals(ship.fly(), TURBO_REPORT);
    }

    @Test
    public void shouldReturnNullWhenGetOffModeIsNull() {
        //when
        ship.setGetOffMode(null);

        //then
        assertNull(ship.getOff());
    }

    @Test
    public void shouldReturnNullWhenLandModeIsNull() {
        //when
        ship.setLandMode(null);

        //then
        assertNull(ship.land());
    }

    @Test
    public void shouldReturnNullWhenFlyModeIsNull() {
        //when
        ship.setFlyMode(null);

        //then
        assertNull(ship.fly());
    }

    @Test
    public void shouldReturnNullWhenNavigableIsNull() {
        //when
        ship.setNavigationMode(null);

        //then
        assertNull(ship.getCurrentLocation());
    }

    @Test
    public void shouldNavigateInDewToEarth() {
        //when
        ship.setNavigationMode(new NavigationInDewToEarth());

        //then
        assertEquals(ship.getCurrentLocation(), "Soon be at home..");
    }

    @Test
    public void shouldNavigateInDewToHelios() {
        //when
        ship.setNavigationMode(new NavigationInDewToHelios());

        //then
        assertEquals(ship.getCurrentLocation(), "Still being in Solar system..");
    }

    @Test
    public void installEngineTest() {
        Engine hamster = new Engine(new ProductInfo("HamsterMotors", "HamsterWheel"), ACCELERATION);
        ship.install(hamster);
        assertTrue(ship.fixEngine());
    }

    @Test
    public void fixingEngineReturnsFalseWhenEngineIsNull() {
        ship.install(null);
        assertFalse(ship.fixEngine());
    }

    @Test
    public void breakingEngineReturnsFalseWhenEngineIsNull() {
        ship.install(null);
        assertFalse(ship.breakEngine());
    }

    @Test
    public void equalsIsReflexive() {
        assertTrue(ship.equals(ship));
    }

    @Test
    public void equalsIsSymmetric() {
        SpaceShip ship2 = ship;
        assertTrue(ship.equals(ship2) && ship2.equals(ship));
    }

    @Test
    public void equalsIsTransitive() {
        SpaceShip ship2 = ship;
        SpaceShip ship3 = ship2;
        assertTrue(ship.equals(ship2) && ship2.equals(ship3) && ship.equals(ship3));
    }

    @Test
    public void equalsNonNullTest() {
        assertFalse(ship.equals(null));
    }

    @Test
    public void hashCodeTest() {
        int hashValueForMultiply = 16;
        assertTrue(ship.hashCode() ==
                (ship.getProductInfo().hashCode() ^ hashValueForMultiply));
    }

    @Test
    public void toStringTest() {
        assertEquals(ship.toString(), ship.getProductInfo());
    }
}
